(function (_window) {
  /**盒子的keyCode与事件的对应 */
  var keysIptv = { 65: "LEFT", 37: "LEFT", 87: "UP", 38: "UP", 68: "RIGHT", 39: "RIGHT", 83: "DOWN", 40: "DOWN", 13: "ENTER", 32: "BACK", 8: "BACK", 36: "HOME", 12: "BACKSPACE", 280: "DEL", 287: "DEL", 18: "MENU", 48: 0, 49: 1, 50: 2, 51: 3, 52: 4, 53: 5, 54: 6, 55: 7, 56: 8, 57: 9, };
  function getCurrentStyle(element, styleProp) {
    if (element.currentStyle) {
      return element.currentStyle[styleProp];
    } else if (window.getComputedStyle) {
      return window.getComputedStyle(element, null).getPropertyValue(styleProp);
    } else {
      return element.style[styleProp];
    }
  }
  function parseFunctionString(input) {
    var hasParentheses = input.indexOf('(') !== -1 && input.indexOf(')') !== -1;
    if (hasParentheses) {
      var regex = /^(\w+)\((.*)\)$/;
      var match = input.match(regex);
      if (match) {
        var funcName = match[1];
        var paramsString = match[2];
        try {
          //整体解析
          var jsonArrayStr = '[' + paramsString.replace(/'/g, '"') + ']';
          var params = JSON.parse(jsonArrayStr);
          return { funcName: funcName, params: params };
        } catch (e) {
          // 整体解析失败时，逐个参数解析
          var paramArray = splitParams(paramsString);
          var params = [];
          for (var i = 0; i < paramArray.length; i++) {
            var param = parseSingleParam(paramArray[i]);
            params.push(param);
          }
          return { funcName: funcName, params: params };
        }
      }
    } else {
      return { funcName: input, params: [] };
    }
    return null;
  }
  // 按逗号切割参数，处理简单场景（不处理嵌套逗号）
  function splitParams(paramsString) {
    var parts = [];
    var current = '';
    var inQuotes = false;
    for (var i = 0; i < paramsString.length; i++) {
      var char = paramsString[i];
      if (char === ',' && !inQuotes) {
        parts.push(current);
        current = '';
      } else {
        if (char === '"' || char === "'") inQuotes = !inQuotes;
        current += char;
      }
    }
    parts.push(current);
    return parts;
  }
  // 解析单个参数：替换单引号 → 尝试 JSON.parse → 失败则返回原始字符串（去空格）
  function parseSingleParam(rawParam) {
    var trimmed = rawParam.replace(/^\s+|\s+$/g, '');
    if (!trimmed) return null;
    try {
      var normalized = trimmed.replace(/'/g, '"');
      return JSON.parse(normalized);
    } catch (e) {
      try {
        return JSON.parse(trimmed);
      } catch (e2) {
        return trimmed;
      }
    }
  }
  function isEleHide(ele) {
    if (typeof ele === "string") ele = document.getElementById(ele)
    if (ele.style.display === "none") return true
    if (ele.style.visibility === "hidden") return true
    if (getCurrentStyle(ele, "display") === "none") return true
    if (getCurrentStyle(ele, "visibility") === "hidden") return true
    if (ele.offsetWidth === 0 || ele.offsetHeight === 0) return true
    return false
  }
  /**获取键盘点击事件的值*/
  function getKeyValue(_code, keys) {
    var _keyboard = keys || keysIptv;
    return _keyboard[_code];
  }
  // 辅助函数：解析函数路径
  function resolveFunction(path, context) {
    var parts = path.split('.');
    var current = context;
    for (var i = 0; i < parts.length; i++) {
      if (current && typeof current === 'object' && current[parts[i]] !== undefined) {
        current = current[parts[i]];
      } else {
        return null;
      }
    }
    if (typeof current === 'function') {
      if (parts && parts[0] && typeof context[parts[0]] === "object") {
        return current.bind(context[parts[0]])
      }
      return current
    }
    return null;
  }
  function find(list, fn) {
    var _itm = { index: -1, item: null };
    for (var i = 0; i < list.length; i++) {
      var _el = list[i];
      if (typeof fn === "function" && fn(_el, i)) {
        _itm.index = i;
        _itm.item = _el;
        break;
      }
    }
    return _itm;
  }
  function filter(list, fn) {
    var _list = [];
    for (var i = 0; i < list.length; i++) {
      var _el = list[i];
      if (typeof fn === "function" && fn(_el, i)) {
        _list.push(_el);
      }
    }
    return _list;
  }
  function forEach(list, callback) {
    for (var i = 0; i < list.length; i++) {
      (function (index) {
        callback(list[index], index, list);
      })(i);
    }
  }
  function map(list, callback) {
    var _list = []
    for (var i = 0; i < list.length; i++) {
      (function (index) {
        _list.push(callback(list[index], index, list) || list[index])
      })(i);
    }
    return _list
  }
  function animate(element, targetPosition, duration, property, callback) {
    property = property || 'left';
    var currentPosition = parseInt(getCurrentStyle(element, property)) || 0;
    var distance = targetPosition - currentPosition;
    var startTime = new Date().getTime();
    var frameDuration = 1000 / 60;
    var intervalId;
    function step() {
      var currentTime = new Date().getTime();
      var elapsedTime = currentTime - startTime;
      if (elapsedTime <= duration) {
        var newPosition = currentPosition + distance * (elapsedTime / duration);
        element.style[property] = Math.round(newPosition) + 'px';
      } else {
        element.style[property] = targetPosition + 'px';
        clearInterval(intervalId);
        if (typeof callback === "function") callback()
      }
    }
    // 启动动画
    intervalId = setInterval(step, frameDuration);
    return intervalId;
  }
  /**getBoundingClientRect*/
  function getRect(dom) {
    var _val = dom.getBoundingClientRect();
    _val["centerX"] = _val.width / 2 + _val.left;
    _val["centerY"] = _val.height / 2 + _val.top;
    return _val;
  }
  function getUid() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
      var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
      return v.toString(16);
    });
  }
  function getDomId(dom) {
    if (!dom) return null
    if (!dom.id) dom.id = getUid()
    return dom.id
  }
  function nextTick(fn) { return setTimeout(fn, 0); }
  _window.focusUtil = { find: find, forEach: forEach, map: map, filter: filter, }
  /**
   * 焦点页面
   * @param { {focusPageEle: Element, useKeyDown: boolean} } params 
   */
  function FocusFrame(params) {
    if (!params.focusPageEle) return console.log("请传入主框架节点");
    //焦点框架列表
    this.switchList = [];
    //弹窗列表
    this.popupList = [];
    //绑定的监听的函数
    this.keyDownFns = {};
    //绑定的监听的函数
    this.lockKeyDown = false;
    //当前页面的dom信息
    this.domFocusPage = params.focusPageEle;
    //是否使用内置的焦点监听
    this.useKeyDown = params.useKeyDown == null ? true : params.useKeyDown;
    this.switchClassName = "focusSwitch";//焦点框架
    this.boxClassName = "focusBox";//盒子
    this.scrollClassName = "focusScroll";//滚动区域
    this.widgetClassName = "focusWidget";//焦点元素
    this.marqueeClassName = "focusMarquee";//跑马灯
    this.focusClassName = "is-focus";//聚焦样式名
    this.darkFocusClassName = "dark-focus";//暗焦样式名
    this.init();
    this.onListenKeyDown();
  }
  FocusFrame.prototype.init = function () {
    var _this = this
    //获取焦点框架列表
    forEach(this.domFocusPage.getElementsByClassName(this.switchClassName), function (_ele) {
      if (_ele.getAttribute("f-type") === "popup") return
      var _switchItem = find(_this.switchList, function (_el) { return _el.ele === _ele }).item;
      if (_switchItem && _switchItem.ele === _ele) {
        _switchItem.init();
      } else {
        _this.switchList.push(_this.createSwitch(_ele));
      }
    })
  };
  FocusFrame.prototype.createSwitch = function (_ele) {
    return new FocusSwitch({
      ele: _ele,
      boxClass: this.boxClassName,
      widgetClass: this.widgetClassName,
      scrollClass: this.scrollClassName,
      marqueeClass: this.marqueeClassName,
      focusClass: this.focusClassName,//聚焦样式名
      darkFocusClass: this.darkFocusClassName,//暗焦样式名
    })
  }
  /** 操作弹窗的显示状态 */
  FocusFrame.prototype.onPopup = function (_ele, show) {
    if (typeof _ele === "string") _ele = document.getElementById(_ele);
    if (!_ele) return
    if (_ele.getAttribute && _ele.getAttribute("f-type") === "popup") {
      _ele.style.display = show ? "block" : "none";
      var _popupIdx = find(this.popupList, function (ev) { return ev.ele === _ele }).index,
        _switchIdx = find(this.switchList, function (ev) { return ev.ele === _ele }).index;
      if (_popupIdx >= 0 && !show) {
        this.popupList.splice(_popupIdx, 1);
        _switchIdx >= 0 && this.switchList.splice(_switchIdx, 1);
      } else if (_popupIdx >= 0 && show) {
        this.popupList[_popupIdx].show = true;
        if (_switchIdx < 0) { this.switchList.push(this.createSwitch(_ele)); }
      } else if (_popupIdx < 0 && !show) {
        _switchIdx >= 0 && this.switchList.splice(_switchIdx, 1);
      } else if (_popupIdx < 0 && show) {
        this.popupList.push({
          ele: _ele,
          show: true
        });
        if (_switchIdx < 0) {
          this.switchList.push(this.createSwitch(_ele));
        }
      }
    } else {
      console.log("传入的不是弹窗元素");
    }
  };
  /**键盘事件监听*/
  FocusFrame.prototype.onEmitKeyDown = function (key, fn) {
    if (typeof key !== "string" || typeof fn !== "function") return;
    this.keyDownFns[key] = fn;
  };
  /**取消键盘事件监听*/
  FocusFrame.prototype.onRemoveKeyDown = function (key) {
    if (typeof key !== "string") return;
    delete this.keyDownFns[key];
  };
  /**清空键盘事件监听 */
  FocusFrame.prototype.onClearKeyDown = function () {
    this.keyDownFns = {};
  };
  /**焦点锁*/
  FocusFrame.prototype.onLock = function (ev) {
    this.lockKeyDown = !!ev;
  };
  /**查找焦点框架*/
  FocusFrame.prototype.findSwitch = function (ele) {
    if (!ele) return null;
    var _item = find(this.switchList, function (ev) { return (typeof ele === "string" ? ev.ele.id : ev.ele) === ele }).item;
    return _item;
  };
  /**键盘事件分发给焦点框架*/
  FocusFrame.prototype.distributeKeyDown = function (_keyCode) {
    if (this.keyDownTimer != null) return
    var _this = this;
    if (_this.lockKeyDown) return;
    for (var fnsKey in _this.keyDownFns) {
      var _fn = _this.keyDownFns[fnsKey];
      if (typeof _fn === "function") {
        var _boardKey = getKeyValue(_keyCode);
        if (_boardKey == null) return;
        _fn(_boardKey);
      }
    }
    forEach(map(_this.switchList, function(ev){ return ev }), function (_switchItem) {
      var _popupIdx = find(_this.popupList, function (_popupItem) { return _popupItem.ele === _switchItem.ele }).index;
      var _dataType = _switchItem.ele.getAttribute("f-type");
      if ((_dataType === "popup" && _popupIdx > -1 && _popupIdx === _this.popupList.length - 1 && _this.popupList[_popupIdx].show) || (_dataType !== "popup" && _this.popupList.length === 0)) {
        _switchItem.onKeyDown(_keyCode);
      }
    })
    this.keyDownTimer = setTimeout(function () { clearTimeout(_this.keyDownTimer); _this.keyDownTimer = null }, 120);
  };
  /** 监听键盘事件分发给焦点框架*/
  FocusFrame.prototype.onListenKeyDown = function () {
    if (this.useKeyDown === false) return
    var _this = this;
    window.addEventListener("keydown", function (ev) {
      _this.distributeKeyDown(ev.keyCode)
    });
  };

  /**
   * 焦点框架
   * @param {{
   * ele: Element, 
   * boxClass: string
   * widgetClass: string
   * scrollClass: string
   * }} params 
   */
  function FocusSwitch(params) {
    /**当前选中的焦点 */
    this.focusItem = null;
    /**焦点框架 Element */
    this.ele = params.ele;
    this.focusClass = params.focusClass;
    this.darkFocusClass = params.darkFocusClass;
    this.scrollTimerList = []
    this.widgetList = []
    this.boxList = []
    /**焦点盒子的className */
    this.boxClass = params.boxClass;
    /**滚动元素的className */
    this.scrollClass = params.scrollClass;
    /**焦点元素的className */
    this.widgetClass = params.widgetClass;
    /**焦点元素的className */
    this.marqueeClass = params.marqueeClass;
    var _this = this
    _this.init();
  }
  /**初始化 */
  FocusSwitch.prototype.init = function () {
    this.upDataWidget()
    if (!this.focusItem) return
    var _onFocus = this.focusItem.ele.getAttribute("onfocus");
    if (_onFocus) this.onEval(this.focusItem.ele, _onFocus, "onfocus");
  };
  /** 焦点移动 */
  FocusSwitch.prototype.onMove = function (_key) {
    if (this.widgetList.length === 0) this.upDataWidget({ scrollTo: false })
    var _focusItem = this.focusItem
    if (!_focusItem) return
    var _widgetList = this.widgetList
    //指定ID移动焦点
    var _nextFocusItem = this.onGoto(_focusItem, this.widgetList, _key)
    //顺序移动焦点
    if (!_nextFocusItem) _nextFocusItem = this.onSequenceAlgorithm(_focusItem, this.widgetList, _key);
    if (!_nextFocusItem) {
      //先查找出不在box中的焦点
      var _list = filter(_widgetList, function (el) { return !el.boxEle || el.boxEle === _focusItem.boxEle; });
      forEach(this.boxList, function (ev) {
        if (ev.ele === _focusItem.boxEle) return
        _list.push(ev);
      })
      var _item = this.onShadowAlgorithm(_focusItem, _list, _key);
      if (!_item) _item = this.onAreaAlgorithm(_focusItem, _list, _key);
      if (!_item) return;
      if (_item.type === this.boxClass) {
        //查看是否有缓存方向的配置项
        var _cacheDir = _item.ele.getAttribute("f-cachedir")
        _cacheDir = _cacheDir ? _cacheDir.split(",") : null
        var _cache = _item.ele.getAttribute("f-cache")
        //如果有缓存的焦点，直接跳转到缓存的焦点
        if (_cache && (!_cacheDir || find(_cacheDir, function (_el) { return _el === _key }).item)) {
          _nextFocusItem = find(_widgetList, function (_el) { return (_el.id === _cache); }).item;
        }
        if (!_nextFocusItem) {
          var widigetListInBox = filter(_widgetList, function (_el) {
            return (_el.boxEle && !isEleHide(_el.ele)) ? _el.boxEle.id === _item.ele.id : null;
          });
          //相交计算
          _nextFocusItem = this.onShadowAlgorithm(_focusItem, widigetListInBox, _key);
          if (!_nextFocusItem) {
            //区域计算
            _nextFocusItem = this.onAreaAlgorithm(_focusItem, widigetListInBox, _key);
          }
        }
      } else {
        _nextFocusItem = find(_widgetList, function (_el) {
          return _el.ele === _item.ele;
        }).item;
      }
    }
    if (!_nextFocusItem) return
    this.onChangeFocus(_nextFocusItem, {
      isAnimate: true,
      isEvent: true,
      key: _key,
      fItem: _focusItem,
    })
  }
  /**更新焦点信息,耗时操作,
   * 获取所有焦点的信息，设置焦点与暗焦的样式，并且滚动到焦点与暗焦所在的区域
   */
  FocusSwitch.prototype.upDataWidget = function (options) {
    options = options || {}
    var _this = this
    //更新所有盒子信息
    this.boxList = map(this.ele.getElementsByClassName(this.boxClass) || [], function (ev) {
      return {
        ele: ev,
        id: getDomId(ev),
        type: _this.boxClass,
        rect: getRect(ev),
      }
    })
    var _focusId = this.ele.getAttribute("f-focusid") || ""
    var _defFocusId = this.ele.getAttribute("f-deffocusid") || ""
    //所有焦点信息，顺便设置所有暗焦
    this.widgetList = map(this.ele.getElementsByClassName(this.widgetClass) || [], function (ev) {
      var _boxEle = find(_this.boxList, function (evBox) { return evBox.ele.contains(ev) });
      ev.classList.remove(_this.focusClass);
      ev.classList.remove(_this.darkFocusClass);
      var _info = {
        ele: ev,
        id: getDomId(ev),
        type: _this.widgetClass,
        boxEle: _boxEle.item,
        rect: getRect(ev),
      }
      if (_focusId === _info.id) { _this.focusItem = _info }
      //暗焦处理
      var _cache = _info.boxEle ? _info.boxEle.ele.getAttribute("f-cache") : null
      if (_cache === _info.id) {
        ev.classList.add(_this.darkFocusClass);
        if (options.scrollTo !== false) {
          _this.onScrollTo(_info.ele, false, false)
        }
      }
      return _info
    })
    if ((!this.focusItem || isEleHide(this.focusItem.ele)) && _defFocusId && (typeof _defFocusId === "string")) {
      this.focusItem = find(this.widgetList, function (ev) {
        return ev.id === _defFocusId
      }).item
    }
    //设置当前焦点
    if (!this.focusItem || isEleHide(this.focusItem.ele)) this.focusItem = this.widgetList[0]
    if (!this.focusItem || isEleHide(this.focusItem.ele)) return
    var _boxEle = this.focusItem.boxEle
    if (_boxEle && _boxEle.ele.getAttribute("f-cache")) {
      var _boxDom = _boxEle.ele
      _boxDom.setAttribute("f-cache", this.focusItem.id)
      forEach(_boxDom.getElementsByClassName(this.widgetClass), function (ev) { ev.classList.remove(_this.darkFocusClass) })
      this.focusItem.ele.classList.add(this.darkFocusClass)
    }
    this.focusItem.ele.classList.add(this.focusClass);
    this.ele.setAttribute("f-focusid", this.focusItem.id)
    this.onMarquee()
    if (options.scrollTo !== false) {
      this.onScrollTo(this.focusItem.ele, false, true)
    }
  }
  /** * 直接跳转到指定元素 */
  FocusSwitch.prototype.onGoto = function (_focus, list, direction) {
    var _newFocus = null;
    var _eleIds = "";
    if (direction === "LEFT") {
      _eleIds = _focus.ele.getAttribute("f-goleft");
    } else if (direction === "RIGHT") {
      _eleIds = _focus.ele.getAttribute("f-goright");
    } else if (direction === "UP") {
      _eleIds = _focus.ele.getAttribute("f-goup");
    } else if (direction === "DOWN") {
      _eleIds = _focus.ele.getAttribute("f-godown");
    }
    if (!_eleIds) return _newFocus;
    _eleIds = _eleIds.split(",");
    find(_eleIds, function (_goId) {
      _newFocus = find(list || [], function (ev) { return (ev.id === _goId && !isEleHide(ev.ele)) }).item
      return _newFocus
    })
    return _newFocus;
  };
  /** * 焦点计算，顺序计算,仅对同一个盒子内部的元素有效 */
  FocusSwitch.prototype.onSequenceAlgorithm = function (_fItem, _list, direction) {
    var _newfItem = null
    if (!_fItem || !_fItem.boxEle) return _newfItem;
    var _sequenceRow = _fItem.boxEle.ele.getAttribute("f-sequencerow");
    if (!_sequenceRow || _sequenceRow <= 0) return _newfItem
    _sequenceRow = _sequenceRow * 1;
    var _widgetEleListInBox = filter(_list, function (ev) {
      return ev.boxEle && ev.boxEle.ele && ev.boxEle.id === _fItem.boxEle.id
    })
    var _focusInBox = find(_widgetEleListInBox, function (ev) { return ev.id === _fItem.id })
    if (!_focusInBox.item) return _newfItem
    var _domIdx = -1
    if (direction === "UP") {
      _domIdx = _focusInBox.index > 0 ? _focusInBox.index - _sequenceRow : -1;
    } else if (direction === "LEFT") {
      var _sequenceLink = _fItem.boxEle.ele.getAttribute("f-sequencelink");
      if ((_sequenceLink === "false") && (_focusInBox.index % _sequenceRow === 0)) {
        _domIdx = -1
      } else {
        _domIdx = _focusInBox.index > 0 ? _focusInBox.index - 1 : -1;
      }
    } else if (direction === "RIGHT") {
      var _sequenceLink = _fItem.boxEle.ele.getAttribute("f-sequencelink");
      if ((_sequenceLink === "false") && ((_focusInBox.index + 1) % _sequenceRow === 0)) {
        _domIdx = -1
      } else {
        _domIdx = (_focusInBox.index < (_widgetEleListInBox.length - _sequenceRow)) ? _focusInBox.index + 1 : -1;
      }
    } else if (direction === "DOWN") {
      _domIdx = (_focusInBox.index < (_widgetEleListInBox.length - _sequenceRow)) ? (_focusInBox.index + _sequenceRow) : -1;
    }
    _newfItem = _widgetEleListInBox[_domIdx]
    return _newfItem;
  };
  /**阴影算法 */
  FocusSwitch.prototype.onShadowAlgorithm = function (widgetItem, widgetList, direction) {
    var currentWidget = widgetItem.ele;
    var currentRect = widgetItem.rect;
    var _select = { item: null, };
    var dis = Infinity, tempDis, xtItemWidget = [];
    for (var i = 0; i < widgetList.length; i++) {
      var tempWidget = widgetList[i].ele;
      if (widgetList[i].type === "focusBox" && !find(tempWidget.getElementsByClassName(this.widgetClass), function (e) { return !isEleHide(e) }).item) {
        continue;
      }
      if (tempWidget === currentWidget) {
        continue;
      }
      var tempWidgetRect = widgetList[i].rect;
      if (tempWidgetRect.height == 0 || tempWidgetRect.width == 0) continue;
      if (direction === "LEFT" && tempWidgetRect.right < currentRect.centerX && tempWidgetRect.left < currentRect.left && tempWidgetRect.top < currentRect.bottom && tempWidgetRect.bottom > currentRect.top) {
        tempDis = currentRect.right - tempWidgetRect.right;
        if (tempDis < dis) {
          _select.item = widgetList[i];
          dis = tempDis;
        } else if (tempDis === dis) {
          xtItemWidget.push({ item: widgetList[i], dis: tempDis })
        }
      } else if (direction === "RIGHT" && tempWidgetRect.left > currentRect.centerX && tempWidgetRect.right > currentRect.right && tempWidgetRect.top < currentRect.bottom && tempWidgetRect.bottom > currentRect.top) {
        tempDis = tempWidgetRect.left - currentRect.left;
        if (tempDis < dis) {
          _select.item = widgetList[i];
          dis = tempDis;
        } else if (tempDis === dis) {
          xtItemWidget.push({ item: widgetList[i], dis: tempDis })
        }
      } else if (direction === "UP" && tempWidgetRect.bottom < currentRect.centerY && tempWidgetRect.top < currentRect.top && tempWidgetRect.left < currentRect.right && tempWidgetRect.right > currentRect.left) {
        tempDis = currentRect.bottom - tempWidgetRect.bottom;
        if (tempDis < dis) {
          _select.item = widgetList[i];
          dis = tempDis;
        } else if (tempDis === dis) {
          xtItemWidget.push({ item: widgetList[i], dis: tempDis })
        }
      } else if (direction === "DOWN" && tempWidgetRect.top > currentRect.centerY && tempWidgetRect.bottom > currentRect.bottom && tempWidgetRect.left < currentRect.right && tempWidgetRect.right > currentRect.left) {
        tempDis = tempWidgetRect.top - currentRect.top;
        if (tempDis < dis) {
          _select.item = widgetList[i];
          dis = tempDis;
        } else if (tempDis === dis) {
          xtItemWidget.push({ item: widgetList[i], dis: tempDis })
        }
      }
    }
    function calcDis(p1, p2) {
      var dx = p2.centerX - p1.centerX;
      var dy = p2.centerY - p1.centerY;
      return Math.sqrt(dx * dx + dy * dy);
    }
    xtItemWidget.push({ item: _select.item, dis: dis })
    var _sqrtDis = Infinity
    forEach(xtItemWidget, function (val) {
      if (!val.item) return
      var _tempSqrtDis = calcDis(currentRect, val.item.rect)
      if (val.dis === dis && _tempSqrtDis < _sqrtDis) {
        _sqrtDis = _tempSqrtDis
        _select.item = val.item
      }
    })
    return _select.item;
  };

  /**区域算法 */
  FocusSwitch.prototype.onAreaAlgorithm = function (widgetItem, widgetList, direction) {
    var currentWidget = widgetItem.ele;
    var currentRect = widgetItem.rect;
    var _select = { item: null, };
    var dis = Infinity, tempDis;
    for (var i = 0; i < widgetList.length; i++) {
      var tempWidget = widgetList[i].ele;
      if (widgetList[i].type === "focusBox" && !find(tempWidget.getElementsByClassName(this.widgetClass), function (e) { return !isEleHide(e) }).item) {
        continue;
      }
      if (tempWidget === currentWidget) {
        continue;
      }
      var tempWidgetRect = widgetList[i].rect;
      if (tempWidgetRect.height == 0 || tempWidgetRect.width == 0) continue;
      if (direction === "LEFT" && tempWidgetRect.right <= currentRect.left) {
        tempDis = Infinity;
        if (tempWidgetRect.bottom < currentRect.top) {
          tempDis = Math.sqrt(Math.pow(currentRect.left - tempWidgetRect.right, 2) + Math.pow(currentRect.top - tempWidgetRect.bottom, 2));
        } else if (tempWidgetRect.top > currentRect.bottom) {
          tempDis = Math.sqrt(Math.pow(currentRect.left - tempWidgetRect.right, 2) + Math.pow(tempWidgetRect.top - currentRect.bottom, 2));
        } else {
          tempDis = currentRect.left - tempWidgetRect.right;
        }
        if (tempDis < dis) {
          _select.item = widgetList[i];
          dis = tempDis;
        }
      } else if (direction === "RIGHT" && tempWidgetRect.left >= currentRect.right) {
        tempDis = Infinity;
        if (tempWidgetRect.bottom < currentRect.top) {
          tempDis = Math.sqrt(Math.pow(tempWidgetRect.left - currentRect.right, 2) + Math.pow(currentRect.top - tempWidgetRect.bottom, 2));
        } else if (tempWidgetRect.top > currentRect.bottom) {
          tempDis = Math.sqrt(Math.pow(tempWidgetRect.left - currentRect.right, 2) + Math.pow(tempWidgetRect.top - currentRect.bottom, 2));
        } else {
          tempDis = tempWidgetRect.left - currentRect.right;
        }
        if (tempDis < dis) {
          _select.item = widgetList[i];
          dis = tempDis;
        }
      } else if (direction === "UP" && tempWidgetRect.bottom <= currentRect.top) {
        tempDis = Infinity;
        if (tempWidgetRect.right < currentRect.left) {
          tempDis = Math.sqrt(Math.pow(currentRect.top - tempWidgetRect.bottom, 2) + Math.pow(currentRect.left - tempWidgetRect.right, 2));
        } else if (tempWidgetRect.left > currentRect.right) {
          tempDis = Math.sqrt(Math.pow(currentRect.top - tempWidgetRect.bottom, 2) + Math.pow(tempWidgetRect.left - currentRect.right, 2));
        } else {
          tempDis = currentRect.top - tempWidgetRect.bottom;
        }
        if (tempDis < dis) {
          _select.item = widgetList[i];
          dis = tempDis;
        }
      } else if (direction === "DOWN" && tempWidgetRect.top >= currentRect.bottom) {
        tempDis = Infinity;
        if (tempWidgetRect.right < currentRect.left) {
          tempDis = Math.sqrt(Math.pow(tempWidgetRect.top - currentRect.bottom, 2) + Math.pow(currentRect.left - tempWidgetRect.right, 2));
        } else if (tempWidgetRect.left > currentRect.right) {
          tempDis = Math.sqrt(Math.pow(tempWidgetRect.top - currentRect.bottom, 2) + Math.pow(tempWidgetRect.left - currentRect.right, 2));
        } else {
          tempDis = tempWidgetRect.top - currentRect.bottom;
        }
        if (tempDis < dis) {
          _select.item = widgetList[i];
          dis = tempDis;
        }
      }
    }
    return _select.item;
  };
  // 更新单个盒子的暗焦
  FocusSwitch.prototype.setDarkFocusById = function (ele, options) {
    options = options || {}
    var _widgetItem = find(this.widgetList, function (_el) { return _el.ele.id === ele }).item;
    if (!_widgetItem) return
    this.setDarkFocus(_widgetItem)
    if (options.scrollTo !== false) this.onScrollTo(_widgetItem.ele)
  };
  // 更新单个盒子的暗焦
  FocusSwitch.prototype.setDarkFocus = function (newFocusItem) {
    if (!newFocusItem || !newFocusItem.boxEle || !newFocusItem.boxEle.ele) return null
    var _boxEle = newFocusItem.boxEle.ele;
    var _cache = _boxEle.getAttribute("f-cache")
    if (!_cache) return null
    _boxEle.setAttribute("f-cache", newFocusItem.ele.id)
    var _this = this
    forEach(_boxEle.getElementsByClassName(this.darkFocusClass), function (darkEle) {
      darkEle.classList.remove(_this.darkFocusClass)
    })
    newFocusItem.ele.classList.add(this.darkFocusClass)
    return newFocusItem.ele.getAttribute("ondarkfocus");
  };
  /**
   * 更新焦点样式
   * newFocus, 当前焦点节点
   * options,   * isAnimate?, 是否动画   * isEvent?, 是否触发焦点事件   * key?, 按下的按钮   * scrollTo: //是否滚动到焦点
   */
  FocusSwitch.prototype.onChangeFocus = function (newFocus, options) {
    options = options || {}
    var _this = this, _onDarkFocus, _oldFocusEle = _this.focusItem
    var _onBlur = _oldFocusEle ? _oldFocusEle.ele.getAttribute("onblur") : null;
    if (_onBlur && _this.onEval(_oldFocusEle.ele, _onBlur, "onblur") === true) return
    this.onStopMarquee(this.focusItem)
    if (typeof newFocus === "string") newFocus = find(this.widgetList, function (ev) { return ev.id === newFocus }).item
    if (!newFocus || !newFocus.ele.classList || isEleHide(newFocus.ele)) return
    //为盒子绑定事件
    if (_oldFocusEle.boxEle != newFocus.boxEle) {
      if (_oldFocusEle.boxEle && this.onEval(_oldFocusEle.boxEle, _oldFocusEle.boxEle.ele.getAttribute("onleave"), options.key || "other") === true) return
      if (newFocus.boxEle && this.onEval(newFocus, newFocus.boxEle.ele.getAttribute("onin"), options.key || "other") === true) return
    }
    if (_oldFocusEle.boxEle != newFocus.boxEle ||_oldFocusEle.id != newFocus.id) {
      if (newFocus.boxEle && this.onEvalFocus(newFocus, newFocus.boxEle.ele.getAttribute("focusin"), options.key || "other") === true) return
    }
    forEach(this.ele.getElementsByClassName(this.focusClass), function (focusEle) {
      focusEle.classList.remove(_this.focusClass)
    })
    newFocus.ele.classList.add(this.focusClass);
    if (newFocus && newFocus.boxEle && newFocus.boxEle.ele && newFocus.boxEle.ele.getAttribute("f-lockcache") != "true") {
      _onDarkFocus = this.setDarkFocus(newFocus)
    }
    this.focusItem = newFocus
    this.ele.setAttribute("f-focusid", this.focusItem.id)
    nextTick(function () {
      if (options.isEvent) {
        if (_onDarkFocus) _this.onEval(ele, _onDarkFocus, options.key || "");
        var _onFocus = newFocus.ele.getAttribute("onfocus") || null;
        if (_onFocus) _this.onEval(newFocus.ele, _onFocus, "onfocus");
      }
      if (options.scrollTo !== false) {
        _this.onScrollTo(newFocus.ele, options.isAnimate, true)
      } else {
        _this.upDataWidget({ scrollTo: false })
      }
    });
    this.onMarquee()
  }
  /**键盘事件分发给对应的函数 */
  FocusSwitch.prototype.onKeyDown = function (_keyCode) {
    var _boardKey = getKeyValue(_keyCode);
    if (_boardKey == null) return;
    //switch上绑定事件
    this.onBindFn(this.ele, _boardKey);
    if (!this.focusItem) return
    //焦点上绑定事件
    if (this.onBindFn(this.focusItem.ele, _boardKey)) return;
    if (this.onMove(_boardKey)) return;
  };
  //执行字符串方法
  FocusSwitch.prototype.onEval = function (ele, fnStr, _key, _options) {
    if (typeof fnStr === "string") {
      var _params = parseFunctionString(fnStr)
      if (!_params) return
      _params.params.push({
        key: _key,
        triggerEle: ele,
        focusWidget: this.focusItem,
        focusSwitch: this,
        params: _options || {}
      });
      var func = resolveFunction(_params.funcName, _window);
      if (typeof func === "function") {
        return func.apply(_window, _params.params);
      }
    }
  };
  //复制上一个字符串方法
  FocusSwitch.prototype.onEvalFocus = function (ele, fnStr, _key, _options) {
    if (typeof fnStr === "string") {
      var _params = parseFunctionString(fnStr)
      if (!_params) return
      _params.params.push({
        key: _key,
        triggerEle: ele,
        focusWidget: ele,
        focusSwitch: this,
        params: _options || {}
      });
      var func = resolveFunction(_params.funcName, _window);
      if (typeof func === "function") {
        return func.apply(_window, _params.params);
      }
    }
  };
  /**绑定事件 */
  FocusSwitch.prototype.onBindFn = function (dom, key) {
    var _ele = dom,
      back = true;
    if (!_ele) return;
    var _fnStr = "";
    if (key === "LEFT" || key === "UP" || key === "RIGHT" || key === "DOWN") {
      _fnStr = _ele.getAttribute("onlistenermove");
      //onListenerMove绑定的事件返回true时，会拦截焦点跳转，拦截跳转仅对焦点起作用
      back = !!this.onEval(_ele, _fnStr, key);
      return back;
    }
    if (key === "ENTER") {
      _fnStr = _ele.getAttribute("onenter");
    }
    if (key === "BACK") {
      _fnStr = _ele.getAttribute("onback");
    }
    if (key === "HOME") {
      _fnStr = _ele.getAttribute("onhome");
    }
    if (key === "BACKSPACE") {
      _fnStr = _ele.getAttribute("onbackspace");
    }
    if (key === "DEL") {
      _fnStr = _ele.getAttribute("ondel");
    }
    if (key === "MENU") {
      _fnStr = _ele.getAttribute("onmenu");
    }
    if (parseInt(key) >= 0 && parseInt(key) <= 9) {
      _fnStr = _ele.getAttribute("oninput");
    }
    this.onEval(_ele, _fnStr, key);
    return back;
  };
  FocusSwitch.prototype.clearScrollTimer = function (_ele) {
    var _scrollTimerList = this.scrollTimerList || []
    var _item = find(_scrollTimerList, function (_el) { return _el.ele === _ele })
    if (_item.item) {
      clearInterval(_item.item.timer);
      this.scrollTimerList.splice(_item.index, 1)
    }
  }
  FocusSwitch.prototype.addScrollTimer = function (_ele, timer) {
    var _scrollTimerList = this.scrollTimerList || []
    var _item = find(_scrollTimerList, function (_el) { return _el.ele === _ele })
    if (!_item.item) {
      this.scrollTimerList.push({ ele: _ele, timer: timer })
    } else {
      this.scrollTimerList[_item.index].timer = timer
    }
  }
  /** 查找到与该焦点元素相关的scroll元素 */
  FocusSwitch.prototype.onFindScrollEle = function (_ele, isFindAllParent) {
    if (!_ele) _ele = this.focusItem.ele;
    if (!_ele) return []
    var _scrollBox = filter(this.ele.getElementsByClassName(this.scrollClass), function (_el) {
      return _el.contains(_ele);
    });
    var _this = this;
    var _list = map(isFindAllParent ? _scrollBox : [_scrollBox[_scrollBox.length - 1]], function (ev) {
      //scroll盒子元素，包含整体.content:scroll的内容元素，包含单项.item:scroll的位置项元素
      var _info = { scroll: null, content: null, item: null };
      if (!ev) return _info;
      /**滚动元素内容盒子的的className，与滚动元素一起使用 */
      var scrollContentClass = _this.scrollClass + "Content";
      var _scrollContent = find(ev.childNodes, function (_el) {
        return _el && _el.classList && _el.classList.contains(scrollContentClass);
      });
      if (!_scrollContent.item) return _info;
      /**滚动子元素的className，与滚动元素一起使用 */
      var scrollItemClass = _this.scrollClass + "Item";
      var _scrollItem = find(ev.getElementsByClassName(scrollItemClass), function (_el) { return _el.contains(_ele) || _ele === _el; });
      _info.scroll = ev;
      _info.content = _scrollContent.item;
      _info.item = _scrollItem.item;
      return _info;
    })
    return _list
  };
  /**
   * 计算焦点元素距离顶部或者最左侧的位置
   * @param {{
   * domLen: number,  parentLen: number,  childLen: number,  eleOffsetStart: number,  childOffsetStart: number,  offset: string | number,  fx: { value: "start" | "end" },
   * }} params 
   * @returns 
   */
  FocusSwitch.prototype.calculateScroll = function (params) {
    var scrollno = 0;
    if (params.parentLen >= params.childLen) return scrollno;
    if (params.offset === "center") {
      scrollno = -(params.eleOffsetStart + params.domLen * 0.5 - params.parentLen / 2);
    } else if (typeof params.offset === "number") {
      var _startNo = -(params.eleOffsetStart - params.offset);
      var _endNo = -(params.eleOffsetStart - (params.parentLen - params.offset - params.domLen));
      if (params.childOffsetStart <= _startNo) {
        params.fx = "start";
      } else if (params.childOffsetStart >= _endNo) {
        params.fx = "end";
      }
      params.fx === "end" ? scrollno = _endNo : scrollno = _startNo;
    }
    if (scrollno > 0) {
      scrollno = 0;
    } else if (scrollno < -params.childLen + params.parentLen) {
      scrollno = -params.childLen + params.parentLen;
    }
    return parseInt(scrollno);
  };
  //触发scroll事件
  FocusSwitch.prototype.onScrollEvent = function (_domInfo, params, _scrollno, _key) {
    var _type = "center"
    //移动到滚动条的开始
    if (_scrollno >= -2) {
      _type = "start"
      this.onEval(_domInfo.scroll, _domInfo.scroll.getAttribute("onscrollstart"), _key, { scrollno: _scrollno })
    }
    if (_scrollno <= -params.childLen + params.parentLen + 2) {
      _type = "end"
      this.onEval(_domInfo.scroll, _domInfo.scroll.getAttribute("onscrollend"), _key, { scrollno: _scrollno })
    }
    this.onEval(_domInfo.scroll, _domInfo.scroll.getAttribute("onscrollmove"), _type, { scrollno: _scrollno })
  }
  // 停止跑马灯
  FocusSwitch.prototype.onStopMarquee = function (focusDom) {
    if(!this.marqueeTimer) this.marqueeTimer = {}
    if (!focusDom || !this.marqueeTimer[focusDom.id]) return
    clearInterval(this.marqueeTimer[focusDom.id])
    this.marqueeTimer[focusDom.id] = null
    var _this = this
    nextTick(function () {
      if (!focusDom) return
      var _marqueeList = focusDom.ele.getElementsByClassName(_this.marqueeClass)
      if (!_marqueeList || !_marqueeList[0]) return
      forEach(_marqueeList, function (marqueeDom) {
        if (marqueeDom.scrollWidth <= marqueeDom.clientWidth) return
        var _content = marqueeDom.getElementsByClassName(_this.marqueeClass + "-content")
        if (!_content || !_content[0]) return
        _content[0].style.left = 0 + "px"
      })
    });
  }
  //启动跑马灯
  FocusSwitch.prototype.onMarquee = function (_id) {
    var _this = this
    var _marqueeList = []
    if(!_this.marqueeTimer) _this.marqueeTimer = {}
    if (_id) {
      if (typeof _id === "string") _id = document.getElementById(_id) 
      if (!_id.style || !_id.classList) return
      _marqueeList = [_id]
    }
    if (!_marqueeList || !_marqueeList[0]) {
      _id = _this.focusItem.ele
      _marqueeList = _this.focusItem.ele.getElementsByClassName(_this.marqueeClass)
    }
    if (!_marqueeList || !_marqueeList[0]) return
    nextTick(function () {
      clearInterval(_this.marqueeTimer[_id.id])
      _this.marqueeTimer[_id.id] = null
      var _list = [], _mar = 20
      forEach(_marqueeList, function (marqueeDom) {
        if (marqueeDom.scrollWidth <= marqueeDom.clientWidth) return////
        var _content = marqueeDom.getElementsByClassName(_this.marqueeClass + "-content")//修改dom结构，用于滚动
        if (!_content || !_content[0]) {
          var _html = marqueeDom.innerHTML
          var _newHtml = '<div class="' + _this.marqueeClass + '-content-item" style="display:inline-block;padding-right:' + _mar + 'px;">' + _html + '</div>'
          marqueeDom.innerHTML = '<div class="' + _this.marqueeClass + '-content" style="position: absolute;left:0;top:0;">' + _newHtml + _newHtml + '</div>'
          _content = marqueeDom.getElementsByClassName(_this.marqueeClass + "-content")
          if (!_content || !_content[0]) return
        }
        _content = _content[0]
        if (!_content) return
        var _itemDom = marqueeDom.getElementsByClassName(_this.marqueeClass + "-content-item")
        if (!_itemDom || !_itemDom[0]) return
        _list.push({
          child: _content,
          itemDom: _itemDom[0],
        })
      })
      if (_list.length > 0) {
        _this.marqueeTimer[_id.id] = setInterval(function () {
          forEach(_list, function (val) {
            var _pos = val.child.style.left.replace("px", "")
            if (_pos < -val.itemDom.offsetWidth) { _pos = 0 }
            val.child.style.left = (_pos - 2) + "px"
          })
        }, 60);
      }
    });
  }
  FocusSwitch.prototype.onScrollTo = function (_ele, isAnimate, isFindAllParent) {
    if (!_ele) return
    isAnimate = isAnimate === false ? false : true;
    if (typeof _ele === "string") { _ele = document.getElementById(_ele); }
    var _domInfoList = this.onFindScrollEle(_ele, isFindAllParent);
    var _this = this
    forEach(_domInfoList, function (_domInfo) {
      if (!_domInfo.content || !_domInfo.item || !_domInfo.scroll) return;
      _this.clearScrollTimer(_domInfo.content);
      var _scrollDir = _domInfo.scroll.getAttribute("f-scroll");
      var _offset = _domInfo.scroll.getAttribute("f-offset");
      var _pos = _domInfo.scroll.getAttribute("f-pos");
      var scrollNumber = 0;
      var _nowScrollNumber = 0;
      var _scrollParams = {}
      var _itemScrollNumber = parseInt(_domInfo.item.getAttribute("f-postion"))
      if (_itemScrollNumber === _itemScrollNumber) {
        scrollNumber = _itemScrollNumber
        _nowScrollNumber = _domInfo.content[(_scrollDir === "X") ? "offsetLeft" : "offsetTop"];
      } else {
        if (_scrollDir === "X") {
          _scrollParams = {
            domLen: getRect(_domInfo.item).width,
            parentLen: getRect(_domInfo.scroll).width,
            childLen: getRect(_domInfo.content).width,
            eleOffsetStart: _domInfo.item.offsetLeft,
            childOffsetStart: _domInfo.content.offsetLeft,
            offset: parseFloat(_offset) || "center",
            fx: _pos || "start"
          }
          scrollNumber = _this.calculateScroll(_scrollParams);
          _nowScrollNumber = _domInfo.content.offsetLeft;
        } else {
          _scrollParams = {
            domLen: getRect(_domInfo.item).height,
            parentLen: getRect(_domInfo.scroll).height,
            childLen: getRect(_domInfo.content).height,
            eleOffsetStart: _domInfo.item.offsetTop,
            childOffsetStart: _domInfo.content.offsetTop,
            offset: parseFloat(_offset) || "center",
            fx: _pos || "start"
          }
          scrollNumber = _this.calculateScroll(_scrollParams);
          _nowScrollNumber = _domInfo.content.offsetTop;
        }
      }
      if (_nowScrollNumber == null) _nowScrollNumber = 0;
      if (_nowScrollNumber === scrollNumber) return
      if (isAnimate) {
        var scrollTimer = animate(_domInfo.content, scrollNumber, 200, _scrollDir === "X" ? "left" : 'top', function () {
          _this.onScrollEvent(_domInfo, _scrollParams, scrollNumber, _scrollDir)
          _this.upDataWidget({ scrollTo: false })
        });
        _this.addScrollTimer(_domInfo.content, scrollTimer)
      } else {
        _domInfo.content.style[_scrollDir === "X" ? "left" : 'top'] = scrollNumber + "px";
        _this.onScrollEvent(_domInfo, _scrollParams, scrollNumber, _scrollDir)
        _this.upDataWidget({ scrollTo: false })
      }
    })
  };
  _window.FocusFrame = FocusFrame
  return FocusFrame
}(window))